﻿//Copyright (C) <2013>  <jonathan cleeve norton> All Rights Reserved 
//Contact jon.norton@fin-plus.co.uk website <http://www.fin-plus.co.uk/>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Text.RegularExpressions;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using FinPlusCommon;
using u = FinPlusUtility.Utility;
using log = Logger.Logger;

namespace FinPlusWPFControls
{
    public partial class FinPlusValueShiftTextBox : FinPlusControl
    {
        public override string Id { get { return GetValue(IdProperty).ToString(); } set { } }
        public override string[] States { get { return new string[] { }; } }
        public override string[] TestStates { get { return new string[] { "ModelTest", "ViewTest", "IsValid" }; } }
        public override IFinPlusFunctions Model { get { return null; } }
        public override string ModelTest { get { return ModelToString(); } }
        public override bool IsValid { get; set; }

        public string ViewTest { get { return ToString(); } }

        public string FunctionName { get { return GetValue(FunctionNameProperty).ToString(); } set { } }
        public string Text { get { return GetValue(TextProperty).ToString(); } set { SetValue(TextProperty, value); } }
        public new bool IsEnabled { get { return (bool)GetValue(IsEnabledProperty); } set { } }
        public object Step { get { return GetValue(StepProperty); } }
        public string StringFormat { get { return GetValue(StringFormatProperty).ToString(); } }
        public Regex InputMask { get { return (Regex)GetValue(InputMaskProperty); } }

        public static readonly DependencyProperty IdProperty = DependencyProperty.Register(Propertys.Id.ToString(), typeof(string), typeof(FinPlusValueShiftTextBox));
        public static readonly DependencyProperty FunctionNameProperty = DependencyProperty.Register(Propertys.FunctionName.ToString(), typeof(string), typeof(FinPlusValueShiftTextBox));
        public static readonly DependencyProperty TextProperty = DependencyProperty.Register(Propertys.Text.ToString(), typeof(string), typeof(FinPlusValueShiftTextBox), new UIPropertyMetadata(Callback));
        public new static readonly DependencyProperty IsEnabledProperty = DependencyProperty.Register(Propertys.IsEnabled.ToString(), typeof(bool), typeof(FinPlusValueShiftTextBox));
        public static readonly DependencyProperty StepProperty = DependencyProperty.Register(Propertys.Step.ToString(), typeof(object), typeof(FinPlusValueShiftTextBox));
        public static readonly DependencyProperty StringFormatProperty = DependencyProperty.Register(Propertys.StringFormat.ToString(), typeof(string), typeof(FinPlusValueShiftTextBox));
        public static readonly DependencyProperty InputMaskProperty = DependencyProperty.Register(Propertys.InputMask.ToString(), typeof(Regex), typeof(FinPlusValueShiftTextBox));

        private enum Propertys { Id, FunctionName, Text, IsEnabled, Step, StringFormat, InputMask }
        private bool _hasSetEnable;

        //construct
        public FinPlusValueShiftTextBox()
        {
            InitializeComponent();
            IsValid = true;

            textBox.Cursor = ((TextBlock)this.Resources["CHit"]).Cursor;
        }

        //common control interface
        public override void Dock(object control, string dock) 
        {
            IsValid = false;
            throw new NotImplementedException();
        }

        public override void Initialise()
        {

        }

        public override void CommandRouter(IFinPlusFunction func)
        {
            try
            {
                CaptureCommand(func);

                switch ((Commands)Enum.Parse(typeof(Commands), func.Name, true))
                {
                    case Commands.ValueShiftUp: ValueShift(true); break;
                    case Commands.ValueShiftDown: ValueShift(false); break;
                    default: throw new Exception(string.Format("event not recognised {0}", func.Name));
                }
            }
            catch (Exception e)
            {
                IsValid = log.Log(Logger.Level.Error, Id, Config, e.Message, e);
            }
        }

        public override void Dispose(){}

        public new string ToString()
        {
            return string.Format("{0}|{1}", textBox.IsEnabled, textBox.Text);
        }

        public string ModelToString()
        {
            return string.Format("{0}|{1}", IsEnabled, Text);
        }

        //private
        private bool ValueShift(bool isUp)
        {
            double v;
            var s = (double)GetValue(StepProperty);
            if( double.TryParse(Text, out v))
                Text = (v + (isUp ? s : -s)).ToString(StringFormat);
            return true;
        }

        private void SetControl(DependencyPropertyChangedEventArgs a)
        {
            //permission
            if (!_hasSetEnable)
            {
                if (!IsEnabled || !GetPermission(FunctionName, Propertys.Id.ToString(), Id).CanWrite)
                {
                    editText.IsReadOnly = true;
                    bUp.IsEnabled = bDown.IsEnabled = false;
                }
                else
                {
                    editText.IsReadOnly = false;
                    bUp.IsEnabled = bDown.IsEnabled = true;
                }
                _hasSetEnable = true;
            }

            //format
            double value;
            if (double.TryParse(a.NewValue.ToString(), out value))
                editText.Foreground = textBox.Foreground = value < 0 ? Brushes.Red : Brushes.Black;
        }

        //cmds
        private new enum Commands { ValueShiftUp, ValueShiftDown, ValuShiftLevel }

        //events
        private static void Callback(DependencyObject d, DependencyPropertyChangedEventArgs a) { ((FinPlusValueShiftTextBox)d).SetControl(a); }
        private void Button_UpClick(object sender, RoutedEventArgs a) { CommandRouter(new Function(Commands.ValueShiftUp.ToString(), Id, User)); }
        private void Button_DownClick(object sender, RoutedEventArgs a) { CommandRouter(new Function(Commands.ValueShiftDown.ToString(), Id, User)); }
        private void Control_LostFocus(object sender, RoutedEventArgs a)
        {
            editBox.Visibility = Visibility.Collapsed;
            textBox.Visibility = Visibility.Visible;
        }
        private void Text_MouseDown(object sender, MouseButtonEventArgs a)
        {
            if (a.ClickCount != 2) return;

            textBox.Visibility = Visibility.Collapsed;
            editBox.Visibility = Visibility.Visible;
        }
        private void Text_PreviewKeyDown(object sender, KeyEventArgs a) { }//TODO
        private void Text_PreviewTextInput(object sender, TextCompositionEventArgs a) { if (InputMask != null && !InputMask.IsMatch(a.Text)) a.Handled = true; }
    }
}
